#include "iot_errno.h"
#include "iot_gpio.h"
#include "stm32f4xx_ll_exti.h"
#include "stm32f4xx_ll_system.h"
#include "ll_gpio.h"
#include "ll_exti.h"
#include "stdio.h"


extern Pin_ST g_pinsGroup[STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX];

unsigned int IoTGpioInit(unsigned int id)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 没有初始化GPIO结构体
    if(!g_pinsGroup[id].isConfig){
        printf("%s error : Please call funtion LL_CONFIG_GPIO to config LL_GPIO_InitTypeDef struct for pull/speed/mode", __func__);
        return IOT_FAILURE;
    }

    STM32_GPIO_GROUP group = id/16;
    // 打开时钟
    LL_AHB1_GRP1_EnableClock(LL_GET_GPIO_CLK(group));
    GPIO_TypeDef *GPIOx = LL_GET_GPIOX(group);
    // 初始化
    if(LL_GPIO_Init(GPIOx, &g_pinsGroup[id].gpioInitStruct)==SUCCESS)
        return  IOT_SUCCESS;
    else
    {
        printf("%s error : LL_GPIO_INIT failed\n", __func__);
        return IOT_FAILURE;
    }
}

unsigned int IoTGpioSetDir(unsigned int id, IotGpioDir dir)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 获取引脚分组
    STM32_GPIO_GROUP group = id/16;
    GPIO_TypeDef* GPIOx = LL_GET_GPIOX(group);
    // 设置引脚方向
    if(dir==IOT_GPIO_DIR_IN)
        LL_GPIO_SetPinMode(GPIOx, LL_GET_HAL_PIN(id%16), LL_GPIO_MODE_INPUT);
    else if(dir==IOT_GPIO_DIR_OUT)
        LL_GPIO_SetPinMode(GPIOx, LL_GET_HAL_PIN(id%16), LL_GPIO_MODE_OUTPUT);
    else{
        printf("%s error : bad dir ...", __func__);
        return IOT_FAILURE;
    }

    return IOT_SUCCESS;
}

unsigned int IoTGpioGetDir(unsigned int id, IotGpioDir *dir)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 获取引脚分组
    STM32_GPIO_GROUP group = id/16;
    GPIO_TypeDef* GPIOx = LL_GET_GPIOX(group);
    // 获取引脚方向
    uint32_t mode = LL_GPIO_GetPinMode(GPIOx, LL_GET_HAL_PIN(id%16));
    if(mode == 0)
        return IOT_GPIO_DIR_IN;
    else
        return IOT_GPIO_DIR_OUT;
}

unsigned int IoTGpioSetOutputVal(unsigned int id, IotGpioValue val)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 获取引脚分组
    STM32_GPIO_GROUP group = id/16;
    GPIO_TypeDef* GPIOx = LL_GET_GPIOX(group);
    // 设置输出值
    if (val == IOT_GPIO_VALUE0) {
        LL_GPIO_ResetOutputPin(GPIOx, LL_GET_HAL_PIN(id%16));
    } else {
        LL_GPIO_SetOutputPin(GPIOx, LL_GET_HAL_PIN(id%16));
    }

    return IOT_SUCCESS;
}

unsigned int IoTGpioGetOutputVal(unsigned int id, IotGpioValue *val)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 获取引脚分组
    STM32_GPIO_GROUP group = id/16;
    GPIO_TypeDef* GPIOx = LL_GET_GPIOX(group);
    // 获取输出值
    *val = LL_GPIO_ReadOutputPin(GPIOx, LL_GET_HAL_PIN(id%16));
    return IOT_SUCCESS;
}

unsigned int IoTGpioGetInputVal(unsigned int id, IotGpioValue *val)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 获取引脚分组
    STM32_GPIO_GROUP group = id/16;
    GPIO_TypeDef* GPIOx = LL_GET_GPIOX(group);
    // 获取输入值
    *val = LL_GPIO_ReadInputPin(GPIOx, LL_GET_HAL_PIN(id%16));
    return IOT_SUCCESS;
}

unsigned int IoTGpioRegisterIsrFunc(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity,
                                    GpioIsrCallbackFunc func, char *arg)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }

    LL_EXTI_InitConfig config;
    // 中断线
    config.initType.Line_0_31 = LL_GET_EXTI_LINE(id%16);
    // 使能中断
    config.initType.LineCommand = ENABLE;
    // 中断类型，stm32f407只有边沿中断
    if(intType == IOT_INT_TYPE_EDGE)
        config.initType.Mode = LL_EXTI_MODE_IT;
    else if(intType==IOT_INT_TYPE_LEVEL){
        printf("%s error : bad params intType, do not support level interrupt...", __func__);
        return IOT_FAILURE;
    }
    // 中断极性，可以是上升沿、下降沿、边沿触发
    if(intPolarity == IOT_GPIO_EDGE_FALL_LEVEL_LOW)
        config.initType.Trigger =  LL_EXTI_TRIGGER_FALLING;
    else if(intPolarity == IOT_GPIO_EDGE_RISE_LEVEL_HIGH)
        config.initType.Trigger = LL_EXTI_TRIGGER_RISING;
    else if(intPolarity == IOT_GPIO_EDGE_RISE_FALL)
        config.initType.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
    else{
        printf("%s error : bad params intPolarity...", __func__);
        return IOT_FAILURE;
    }
    config.Gpiox = LL_GET_GPIOX(id/16);;
    config.PinReg = LL_GET_HAL_PIN(id%16);
    config.Extihandler = func;
    // 初始化中断
    if(LL_SETUP_EXTI(&config, id%16, id, id/16) != SUCCESS)
        return IOT_FAILURE;
    return IOT_SUCCESS;
}

unsigned int IoTGpioUnregisterIsrFunc(unsigned int id)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    uint8_t pin = id%16;
    // 修改中断向量为空
    if (pin < 5) {
        NVIC_SetVector(EXTI0_IRQn + pin, NULL);
    } else if (pin >= 5 && pin < 10) {
        NVIC_SetVector(EXTI9_5_IRQn, NULL);
    } else if (pin >= 10 && pin < 16) {
        NVIC_SetVector(EXTI15_10_IRQn, NULL);
    }
    return IOT_SUCCESS;
}

unsigned int IoTGpioSetIsrMask(unsigned int id, unsigned char mask)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }
    // 关闭中断
    LL_EXTI_DisableIT_0_31(LL_GET_EXTI_LINE(id%16));
    return IOT_SUCCESS;
}

unsigned int IoTGpioSetIsrMode(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity)
{
    return IoTGpioRegisterIsrFunc(id, intType, intPolarity, g_pinsGroup[id].handler, NULL);
}

unsigned int IoTGpioDeinit(unsigned int id)
{
    // 引脚超出范围
    if (id<0 || id>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX) {
        printf("%s line %d error : bad pin num %d ...\n", __func__, __LINE__, id);
        return IOT_FAILURE;
    }

    GPIO_TypeDef* GPIOx = LL_GET_GPIOX(id/16);
    if(LL_GPIO_DeInit(GPIOx)!=SUCCESS){
        printf("%s error : LL_GPIO_DeInit failed\n", __func__);
        return IOT_FAILURE;
    }

    return  IOT_SUCCESS;
}